import type { IntervalTaskProps } from '../../lib/timer_manager'
import type { IUserCenterModule } from '../../types/interfaces'
import { RequestExecutor } from '../../lib/request'
import { TimerManager } from '../../lib/timer_manager'
import { ToolKit } from '../../lib/utils/toolkit'
import { logger, PROJECT_PREFIX, TIME_UNITS } from '../../types/constants'
import {
  DEFAULT_MAXIM_TEXT,
  MAXIM_API_URL,
  MAXIM_INDEX_URL,
} from '../../types/constants/web_link'
import { SYMBOLS } from '../../types/interfaces'

/**
 * 一言数据接口定义
 */
export interface IHitokotoData {
  id: number
  uuid: string
  hitokoto: string
  type: string
  from: string
  from_who: string | null
  creator: string
  creator_uid: number
  reviewer: number
  commit_from: string
  created_at: string
  length: number
}

// TODO: 公告滚动时有模糊感
export class Announcement implements IUserCenterModule {
  name: string = 'Announcement'
  private announcements: AnnouncementConfig[]
  private maximRefreshTask: IntervalTaskProps = {
    id: 'announcement-maxim-refresh',
    interval: TIME_UNITS.COMMON.INTERVALS.THREE_MINUTES,
    running: false,
  }

  private isFetching = false // 防止重复请求
  private maximElement?: JQuery<HTMLElement>
  private static instance: Announcement
  private readonly executor = RequestExecutor.getInstance()
  private readonly timerManager: TimerManager = TimerManager.getInstance()
  private currentRequestController: AbortController | null = null

  constructor() {
    this.announcements = [
      {
        id: 'welcome',
        content: `${SYMBOLS.STATUS.NOTIFICATION} 感谢您启用这份『数字清净』，愿为您裁去浮华，留一方冲浪净土。${SYMBOLS.NATURE.EARTH}${SYMBOLS.STATUS.SPARKLES.repeat(3)}`,
        priority: 1,
        startTime: new Date().toLocaleString(),
        endTime: new Date(Date.now() + TIME_UNITS.COMMON.INTERVALS.ONE_WEEK).toLocaleString(),
      },
    ]
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): Announcement {
    if (!Announcement.instance) {
      Announcement.instance = new Announcement()
    }
    return Announcement.instance
  }

  destroy(): void {
    // 1. 取消未完成请求
    if (this.isFetching && this.currentRequestController)
      this.currentRequestController.abort()
    this.isFetching = false
    this.currentRequestController = null

    // 2. 清除定时器
    if (this.maximRefreshTask.running) {
      this.timerManager.clearInterval(this.maximRefreshTask.id)
      this.maximRefreshTask.running = false
    }

    // 3. 清理 DOM 引用和事件
    if (this.maximElement) {
      this.maximElement.off() // 移除所有 jQuery 事件
      this.maximElement = undefined
    }
  }

  /**
   * 获取并展示一言数据
   */
  private fetchMaxim = async () => {
    if (this.isFetching)
      return

    this.isFetching = true

    if (!this.maximElement || !this.maximElement.length)
      return

    try {
      // 创建取消控制器
      this.currentRequestController = new AbortController()

      logger.debug(`[${this.name}] 开始获取一言数据...`)

      const response = await this.executor.executeRequest<IHitokotoData>(MAXIM_API_URL, {
        signal: this.currentRequestController.signal, // 传递取消信号
      })

      // 请求完成后清理控制器
      this.currentRequestController = null

      if (!response.success)
        throw new Error(`一言数据获取失败: ${response.error?.message || '未知错误'}`)

      const data = response.data!
      this.processMaximData(data, response.duration)
    }
    catch (error: any) {
      this.handleMaximError(error)
    }
    finally {
      this.isFetching = false
      this.currentRequestController = null // 确保清理控制器
    }
  }

  /**
   * 处理成功的一言数据
   */
  private processMaximData(data: IHitokotoData, duration: number) {
    if (!this.maximElement?.length)
      return

    if (!data || !data.hitokoto) {
      this.setDefaultMaxim()
      return
    }

    logger.success(`[${this.name}] 一言数据获取成功，耗时: ${duration} ms`, data)

    const fromWho = data?.from_who?.trim() ? `${data.from_who}：` : ''
    this.maximElement
      ?.text(`${fromWho}${data.hitokoto}`)
      .attr('href', `https://hitokoto.cn/?uuid=${data.uuid}`)
  }

  /**
   * 处理一言请求错误
   */
  private handleMaximError(error: any) {
    // 检查是否为取消错误
    if (ToolKit.error.isAbortError(error)) {
      logger.debug(`[${this.name}] 一言请求已被取消`)
      return
    }

    this.setDefaultMaxim()

    throw error
  }

  /**
   * 设置默认一言
   */
  private setDefaultMaxim() {
    if (!this.maximElement?.length)
      return

    this.maximElement?.text(DEFAULT_MAXIM_TEXT).attr('href', MAXIM_INDEX_URL)
  }

  private initMaxim() {
    this.maximElement = $('#hitokoto-link') // 缓存 DOM 引用
    const $container = $('#hitokoto')

    if (!$container || $container.length === 0)
      return

    this.timerManager.createTimerTask({
      id: this.maximRefreshTask.id,
      callback: this.fetchMaxim.bind(this),
      interval: this.maximRefreshTask.interval,
      immediate: true,
    })

    this.maximRefreshTask.running = true
  }

  public generateHTML(): string {
    const now = new Date()
    const validAnnouncements = this.announcements.filter((ann) => {
      const start = new Date(ann.startTime)
      const end = new Date(ann.endTime)
      return now >= start && now <= end
    }).sort((a, b) => b.priority - a.priority)

    if (validAnnouncements.length === 0)
      return ''

    const topAnnouncement = validAnnouncements[0]

    return `
      <div class="announcement-container">
        <div class="announcement-content">
          <div class="marquee-wrapper">
            <div class="marquee-content">${topAnnouncement.content}</div>
          </div>
        </div>
        <div id="hitokoto">
          <a id="hitokoto-link"></a>
        </div>
      </div>
    `
  }

  private initMarquee() {
    const $content = $('.user-center-modal .marquee-content')
    const content = $content.text()

    // 计算理想时长（字数和优先级的函数）
    const duration = Math.min(
      Math.max(
        10000, // 最小10秒
        10000 + (content.length * 300), // 每字+0.3秒
      ),
      60000, // 最大60秒
    )

    // 应用动画
    $content.css({
      'animation-duration': `${duration}ms`,
      'animation-timing-function': 'cubic-bezier(0.1, 0, 0.9, 1)',
    })

    // 添加用户交互控制
    $content.parent()
      .on('mouseenter touchstart', () => $content.css('animation-play-state', 'paused'))
      .on('mouseleave touchend', () => $content.css('animation-play-state', 'running'))
  }

  public handleOpen(): void {
    if (!ToolKit.serviceAlert.isUserAlert())
      return

    this.initMarquee()
    this.initMaxim()
  }

  public styles(): string {
    return `
      .announcement-container {
        position: absolute !important;
        top: 0;
        left: 0;
        height: 60px;
        width: 100%;
        margin: 0 auto;
        background: var(--${PROJECT_PREFIX}-theme-announcement-bg) !important;
        overflow: visible;
        /* 防止子元素模糊 */
        filter: blur(0);
        transform: translateZ(0);
        
        .announcement-content {
          font-size: 15px;
          line-height: 1.5;
          color: var(--${PROJECT_PREFIX}-theme-announcement-text) !important;
          position: absolute;
          width: 100%;
          height: 100%;
          display: flex;
          align-items: center;
          /* 字体渲染优化 */
          text-rendering: geometricPrecision;
          -webkit-font-smoothing: subpixel-antialiased;
          -moz-osx-font-smoothing: grayscale;
          font-smooth: always;
          text-shadow: 0 0 0 transparent; /* 修复某些浏览器的模糊问题 */
          
          .marquee-wrapper {
            width: 100%;
            white-space: nowrap;
            overflow: hidden; /* 嵌套的溢出隐藏 */
            
            .marquee-content {
              display: inline-block;
              padding-left: 100%; /* 初始位置在右侧 */
              white-space: nowrap;
              animation: marquee 25s linear infinite; /* 动画设置 */
              /* 禁用字体缩放 */
              text-size-adjust: 100%;
              /* 动画性能提示 */
              will-change: transform;
              /* 启用GPU加速 */
              transform: translate3d(0, 0, 0) translateZ(0);
              /* 优化3D渲染 */
              backface-visibility: hidden;
              -webkit-backface-visibility: hidden;
              /* 创建3D上下文 */
              perspective: 1000px;
              /* 禁用子像素抗锯齿 */
              font-smoothing: subpixel-antialiased;
            }
          }
        }
        
        #hitokoto #hitokoto-link {
          position: absolute;
          right: 15px;
          bottom: -12px;
          transform: translateY(100%);  /* 将下移距离转为百分比 */
          font-style: italic;
          text-align: right;
          color: #666;
          font-size: 12px;
          padding: 2px 8px;
          text-decoration: none;
          
          &:hover {
            color: #999;
            text-decoration: none;
          }
        }
      }

      /* 针对不同浏览器的优化 */
      @-webkit-keyframes marquee {
        0% {
          -webkit-transform: translate3d(0, 0, 0);
        }
        100% {
          -webkit-transform: translate3d(-100%, 0, 0);
        }
      }
    `
  }
}
